﻿using Cemit.PolyProto;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace Cemit.NetFramework
{
    internal static class PolySocketPingExtensions
    {
        readonly static Dictionary<PolySocket, LastTimeData> pingTimes 
            = new Dictionary<PolySocket, LastTimeData>();

        class LastTimeData
        {
            public float LastPingTime { get; private set; }
            public float LastPongTime { get; private set; }

            public LastTimeData SetPing(float time)
            {
                LastPingTime = time;
                return this;
            }

            public LastTimeData SetPong(float time)
            {
                LastPongTime = time;
                return this;
            }
        }

        public static bool IsTimeout(this PolySocket socket)
        {
            if (!pingTimes.ContainsKey(socket))
            {
                return false;
            }   

            if (Time.time - pingTimes[socket].LastPongTime > PolyNetwork.PingTimeout)
            {
                return true;
            }

            return false;
        }

        public static PolySocket RefreshPing(this PolySocket socket)
        {
            if (!pingTimes.ContainsKey(socket))
            {
                pingTimes.Add(socket, new LastTimeData().SetPing(Time.time).SetPong(Time.time));
                return socket;
            } 

            //向服务器发出ping消息，并在接受服务器传回的pong时更新pong时间
            if (Time.time - pingTimes[socket].LastPingTime > PolyNetwork.PingInterval)
            {
                socket.Send(new Msg_Net_Ping())
                    .AddCallback<Msg_Net_Pong>(m => pingTimes[socket].SetPong(Time.time));

                pingTimes[socket].SetPing(Time.time);
            }

            return socket;
        }

        /// <summary>
        /// 获取延迟，未连接或无记录则返回-1，ping正在刷新则返回一个其他负数
        /// </summary>
        public static float GetPing(this PolySocket polySocket)
        {
            if (!pingTimes.ContainsKey(polySocket))
            {
                return -1;
            }

            float ret = pingTimes[polySocket].LastPongTime - pingTimes[polySocket].LastPingTime;

            if (ret < 0.01f)
                return 0.01f;
            if (ret < 1)
                return float.Parse(string.Format("{0:N2}", ret)); //保留两位
            else
                return Convert.ToInt32(ret); //转为整数

            //返回string类型的ping LANQ 2019/9/15

            //Debug.LogInfo($"ping:{GetPing()}ms");

            //string GetPing()
            //{
            //    float ping = lastPongTime - lastPingTime;
            //    if (ping < 0.01)
            //        return "<0.01";
            //    if (ping < 1)
            //        return string.Format("{0:N2}", ping);
            //    else
            //        return Convert.ToInt32(ping).ToString();
            //}
        }
    }
}
